package com.ls.fw.web.core.servlet.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ls.fw.web.core.servlet.constant.Constant;
import com.ls.fw.web.core.servlet.http.util.IPAddress;
import com.ls.fw.web.core.servlet.http.util.IPRange;
import com.ls.fw.web.core.servlet.utils.HttpUtils;
import com.ls.fw.web.core.servlet.utils.ObjectUtil;


/**
 * <!--================权限 设置================-->     
    <filter>     
        <filter-name>Authentication</filter-name>     
        <filter-class>com.ls.fw.filter.UrlFilter</filter-class>     
        <init-param>     
            <param-name>onError</param-name>     
            <param-value>/index.html</param-value>     
        </init-param>
        <!-- 访问控制
		    deny优先于allow，如果在deny列表中，就算在allow列表中，也会被拒绝。
		        如果allow没有配置或者为空，则允许所有访问
		配置的格式
			  <IP>
			  或者
			  <IP>/<SUB_NET_MASK_size>
			其中
			  128.242.127.1/24
			24表示，前面24位是子网掩码，比对的时候，前面24位相同就匹配。
			如：128.242.127.1/24,128.242.128.1
		 -->
		<init-param>
	        <param-name>allow</param-name>
	        <param-value>10.4.126.101</param-value>
	    </init-param>
	    <init-param>
	        <param-name>deny</param-name>
	        <param-value>138.118.72.24</param-value>
	    </init-param>
       <!-- 
       <init-param>     
            <param-name>excludedUrl</param-name>     
            <param-value>/index.html</param-value>     
        </init-param>
        <init-param>     
            <param-name>includedUrl</param-name>     
            <param-value>/index.html</param-value>     
        </init-param>   
        -->   
    </filter>     
 * @author Defender
 * 2014年2月16日 下午12:19:27
 */
public class UrlFilter implements Filter {

	protected static final Logger logger = LoggerFactory
			.getLogger(UrlFilter.class);

	private FilterConfig filterConfig;

	public static final String PARAM_NAME_ALLOW = "allow";
	public static final String PARAM_NAME_DENY = "deny";

	private String excludedUrl = "";

	private String includedUrl = "";

	protected List<IPRange> allowList = new ArrayList<IPRange>();
	protected List<IPRange> denyList = new ArrayList<IPRange>();

	private static final String deiyPage = "index.html";
	
	@Override
	public void destroy() {
		this.filterConfig = null;
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
		this.initAuthEnv();
	}

	private String getInitParameter(String name) {
		return filterConfig.getInitParameter(name);
	}

	private void initAuthEnv() {
		
		excludedUrl = getInitParameter(Constant.excludedUrl);
		logger.debug("excludedUrl:" + excludedUrl);
		
		includedUrl = getInitParameter(Constant.includedUrl);
		logger.debug("includedUrl:" + includedUrl);
		
		try {
			String param = getInitParameter(PARAM_NAME_ALLOW);
			if (ObjectUtil.isNotEmpty(param)) {
				param = param.trim();
				String[] items = param.split(",");

				for (String item : items) {
					if (ObjectUtil.isEmpty(item)) {
						continue;
					}

					IPRange ipRange = new IPRange(item);
					allowList.add(ipRange);
				}
			}
		} catch (Exception e) {
			String msg = "initParameter config error, allow : "
					+ getInitParameter(PARAM_NAME_ALLOW);
			logger.error(msg, e);
		}
		logger.debug("allowList:" + allowList);
		try {
			String param = getInitParameter(PARAM_NAME_DENY);
			if (ObjectUtil.isNotEmpty(param)) {
				param = param.trim();
				String[] items = param.split(",");

				for (String item : items) {
					if (ObjectUtil.isEmpty(item)) {
						continue;
					}

					IPRange ipRange = new IPRange(item);
					denyList.add(ipRange);
				}
			}
		} catch (Exception e) {
			String msg = "initParameter config error, deny : "
					+ getInitParameter(PARAM_NAME_DENY);
			logger.error(msg, e);
		}
		logger.debug("denyList:" + denyList);
	}

	
	/**
	 * 過錄
	 */
	@Override
	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = ((HttpServletResponse) servletResponse);
		String url = request.getServletPath();
		if (url == null) {
			url = "";
		}
		if (validUrl(url)) {
			chain.doFilter(request, response);
		} else {
			if (!isPermittedRequest(request)) {
				response.setCharacterEncoding("utf-8");
				response.setContentType("text/html;charset=UTF-8");
				response.sendRedirect(deiyPage);// 返回登录页面
			} else {
				chain.doFilter(request, response);
			}
		}
	}

	/**
	 * 是否是允许访问的请求
	 * 
	 * @author Defender 2014年2月16日 下午12:03:32
	 * @param request
	 * @return
	 */
	private boolean isPermittedRequest(HttpServletRequest request) {
		String remoteAddress = HttpUtils.getIp(request);
		return isPermittedRequest(remoteAddress);
	}

	/**
	 * 是否是允许访问的ip
	 * 
	 * @author Defender 2014年2月16日 下午12:03:04
	 * @param remoteAddress
	 * @return
	 */
	private boolean isPermittedRequest(String remoteAddress) {
		logger.debug("remoteAddress:" + remoteAddress);
		boolean flag = false;
		if ("127.0.0.1".equals(remoteAddress)) {
			return true;
		}
		boolean ipV6 = remoteAddress != null
				&& remoteAddress.indexOf(':') != -1;
		if (ipV6) {
			if ("0:0:0:0:0:0:0:1".equals(remoteAddress)) {
				flag = true;
			}else{
				if (denyList.size() == 0 && allowList.size() == 0) {
					flag = true;
				}
			}
			return flag;
		}else{
			boolean existDeny = false;
			IPAddress ipAddress = new IPAddress(remoteAddress);
			for (IPRange range : denyList) {
				if (range.isIPAddressInRange(ipAddress)) {
					flag =  false;
					existDeny = true;
					break;
				}
			}
			if(!existDeny){
				if (allowList.size() > 0) {
					for (IPRange range : allowList) {
						if (range.isIPAddressInRange(ipAddress)) {
							flag = true;
							break;
						}
					}
					flag = false;
				}
			}
		}
		return flag;
	}

	private boolean validUrl(String url) {
		boolean flag = false;
		logger.debug("url:" + url);
		if ("/index.html".equals(url)) {
			flag = true;
		}
		return flag;
	}

//	private boolean validIP(String ip) {
//		boolean flag = false;
//		if ("127.0.0.1".equals(ip.trim())) {
//			flag = true;
//		} else if ("0:0:0:0:0:0:0:1".equals(ip.trim())) {
//			flag = true;
//		}
//		if (this.allow == null || "".equals(allow)) {
//			flag = true;
//			// allow = PropertyUtil.readByKey(Constant.ALLOW);
//			// logger.debug("allow:"+allow);
//		}
//		String str = this.allow;
//		if (str != null) {
//			String[] strs = str.split(",");
//			for (String string : strs) {
//				if (string.trim().equals(ip.trim())) {
//					flag = true;
//					break;
//				}
//			}
//		}
//		return flag;
//	}
}
